from flask import Flask, render_template, jsonify, request, send_from_directory, send_file, redirect
from datetime import datetime, timedelta
import json
import pymysql
import numpy as np
import pandas as pd
import os
import threading
import time
import re
import logging
from utils.logging_config import logger
from utils.data_processor import DataProcessor
from utils.data_processor1 import DataProcessor as DataProcessor1
from utils.scheduling import update_schedule
from urllib.parse import unquote
from flask_cors import CORS

# ==================== 初始化Flask应用 ====================
app = Flask(__name__)
CORS(app)  # 允许跨域

# ==================== 自定义JSON编码器 ====================
class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        elif isinstance(obj, datetime):
            return obj.strftime("%Y-%m-%d %H:%M:%S")
        return super(CustomJSONEncoder, self).default(obj)

app.json_encoder = CustomJSONEncoder

# ==================== 配置信息 ====================
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': '123456',
    'db': 'kun',
    'charset': 'utf8',
    'cursorclass': pymysql.cursors.DictCursor
}
MODEL_PATH = "model_dict.pkl"
TABLE_NAMES = ['kun2_1', 'kun2_2']
START_DATE = datetime(2025, 1, 1)
CHART_DIR = "生产线趋势图"
DATA_FOLDER = 'data'
RESULT1_PATH = os.path.join(DATA_FOLDER, 'result4-1.xlsx')
RESULT2_PATH = os.path.join(DATA_FOLDER, 'result4-2.xlsx')

# ==================== 初始化处理器 ====================
history_processors = {
    'M201': DataProcessor(DB_CONFIG, MODEL_PATH, START_DATE),
    'M202': DataProcessor(DB_CONFIG, MODEL_PATH, START_DATE)
}

realtime_processors = {
    'M201': DataProcessor1(DB_CONFIG, MODEL_PATH, START_DATE),
    'M202': DataProcessor1(DB_CONFIG, MODEL_PATH, START_DATE)
}

# ==================== 全局状态 ====================
fault_history = {'M201': [], 'M202': []}
fault_history_lock = threading.Lock()

realtime_state = {
    'M201': {'running': False, 'active_faults': [], 'recent_history': [], 'today_trend': [0]*24, 'latest_data': None},
    'M202': {'running': False, 'active_faults': [], 'recent_history': [], 'today_trend': [0]*24, 'latest_data': None}
}
realtime_lock = threading.Lock()

schedule_status = {
    'is_processing': False,
    'last_result': None,
    'last_error': None
}

# ==================== 用户认证相关 ====================
from werkzeug.security import check_password_hash, generate_password_hash
from functools import wraps
import jwt
import datetime as dt

# JWT配置
JWT_SECRET = 'your-secret-key-here'  # 生产环境请使用环境变量
JWT_EXPIRATION_HOURS = 24

# 用户数据库（生产环境请使用真实数据库）
USERS = {
    'admin': {
        'password': generate_password_hash('admin123'),
        'role': 'admin',
        'name': '系统管理员',
        'employee_id': 'A2023001',
        'department': '生产管理部',
        'position': '部门经理',
        'email': 'admin@example.com',
        'phone': '13800138000'
    },
    'manager': {
        'password': generate_password_hash('manager123'),
        'role': 'manager',
        'name': '张经理',
        'employee_id': 'A2023002',
        'department': '生产管理部',
        'position': '生产经理',
        'email': 'zhang@example.com',
        'phone': '13800138001',
    },
    'li': {
        'password': generate_password_hash('li123'),
        'role': 'manager',
        'name': '李主管',
        'employee_id': 'A2023003',
        'department': '生产车间',
        'position': '车间主管',
        'email': 'li@example.com',
        'phone': '13800138002'
    }
}

# 会话管理（实际项目中应使用更安全的方案）
active_sessions = {}

def generate_token(username, user_info):
    """生成JWT令牌"""
    payload = {
        'username': username,
        'role': user_info['role'],
        'name': user_info['name'],
        'exp': dt.datetime.utcnow() + dt.timedelta(hours=JWT_EXPIRATION_HOURS),
        'iat': dt.datetime.utcnow()
    }
    return jwt.encode(payload, JWT_SECRET, algorithm='HS256')

def verify_token(token):
    """验证JWT令牌"""
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
        return payload
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

def login_required(f):
    """登录验证装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        token = None
        
        # 从请求头获取token
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            try:
                token = auth_header.split(' ')[1]  # Bearer <token>
            except IndexError:
                return jsonify({'success': False, 'message': '无效的认证头格式'}), 401
        
        # 从cookie获取token（备选）
        if not token and 'auth_token' in request.cookies:
            token = request.cookies['auth_token']
            
        if not token:
            return jsonify({'success': False, 'message': '需要登录才能访问'}), 401
            
        payload = verify_token(token)
        if not payload:
            return jsonify({'success': False, 'message': '登录已过期，请重新登录'}), 401
            
        # 将用户信息添加到请求对象
        request.current_user = payload
        return f(*args, **kwargs)
    
    return decorated_function

# 登录接口
@app.route('/api/login', methods=['POST'])
def login():
    """用户登录"""
    try:
        data = request.get_json()
        username = data.get('username', '').strip()
        password = data.get('password', '')
        
        if not username or not password:
            return jsonify({
                'success': False,
                'message': '用户名和密码不能为空'
            }), 400
            
        # 验证用户
        user_info = USERS.get(username)
        if not user_info or not check_password_hash(user_info['password'], password):
            return jsonify({
                'success': False,
                'message': '用户名或密码错误'
            }), 401
            
        # 生成token（简化版，实际应更复杂）
        import secrets
        token = secrets.token_hex(16)
        active_sessions[token] = {
            'username': username,
            'login_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'user_info': user_info
        }

        # 记录登录日志
        logger.info(f"用户登录成功 - 用户名: {username}, 角色: {user_info['role']}")
        
        return jsonify({
            'success': True,
            'message': '登录成功',
            'token': token,
            'user': {
                'username': username,
                'name': user_info['name'],
                'role': user_info['role']
            }
        })
        
    except Exception as e:
        logger.error(f"登录异常: {str(e)}", exc_info=True)
        return jsonify({
            'success': False,
            'message': '登录失败，请稍后重试'
        }), 500

# 登出接口
@app.route('/api/logout', methods=['POST'])
@login_required
def logout():
    """用户登出"""
    try:
        username = request.current_user['username']
        logger.info(f"用户登出 - 用户名: {username}")
        
        return jsonify({
            'success': True,
            'message': '登出成功'
        })
        
    except Exception as e:
        logger.error(f"登出异常: {str(e)}")
        return jsonify({
            'success': False,
            'message': '登出失败'
        }), 500

@app.route('/api/user/profile', methods=['GET'])
@login_required
def get_user_profile():
    try:
        # 从session或token中获取用户名
        username = request.current_user['username']
        user_info = USERS.get(username)
        
        if not user_info:
            return jsonify({'success': False, 'message': '用户不存在'})
        
        # 返回完整的用户信息（排除密码）
        user_data = {k: v for k, v in user_info.items() if k != 'password'}
        user_data['username'] = username
        
        return jsonify({
            'success': True,
            'user_info': user_data
        })
        
    except Exception as e:
        logger.error(f"获取用户信息异常: {str(e)}")
        return jsonify({'success': False, 'message': '获取用户信息异常'})

@app.route('/api/user/update-profile', methods=['POST'])
@login_required
def update_user_profile():
    try:
        token = request.headers.get('Authorization') or request.args.get('token')
        data = request.get_json()
        
        user_session = active_sessions.get(token)
        if not user_session:
            return jsonify({'success': False, 'message': '用户信息不存在'})
        
        # 更新用户信息（实际项目中应更新数据库）
        user_info = user_session['user_info']
        updatable_fields = ['name', 'department', 'position', 'email', 'phone']
        
        for field in updatable_fields:
            if field in data:
                user_info[field] = data[field]
        
        logger.info(f"用户信息更新: {user_session['username']}")
        return jsonify({'success': True, 'message': '信息更新成功'})
        
    except Exception as e:
        logger.error(f"更新用户信息异常: {str(e)}")
        return jsonify({'success': False, 'message': '更新用户信息异常'})

@app.route('/api/user/change-password', methods=['POST'])
@login_required
def change_password():
    try:
        token = request.headers.get('Authorization') or request.args.get('token')
        data = request.get_json()
        
        current_password = data.get('current_password')
        new_password = data.get('new_password')
        confirm_password = data.get('confirm_password')
        
        if not all([current_password, new_password, confirm_password]):
            return jsonify({'success': False, 'message': '请填写完整密码信息'})
        
        if new_password != confirm_password:
            return jsonify({'success': False, 'message': '新密码与确认密码不一致'})
        
        user_session = active_sessions.get(token)
        if not user_session:
            return jsonify({'success': False, 'message': '用户信息不存在'})
        
        user_info = user_session['user_info']
        if user_info['password'] != generate_password_hash(current_password):
            return jsonify({'success': False, 'message': '当前密码错误'})
        
        # 更新密码（实际项目中应更新数据库）
        user_info['password'] = generate_password_hash(new_password)
        
        logger.info(f"用户密码修改: {user_session['username']}")
        return jsonify({'success': True, 'message': '密码修改成功'})
        
    except Exception as e:
        logger.error(f"修改密码异常: {str(e)}")
        return jsonify({'success': False, 'message': '修改密码异常'})

# 登录页面路由
@app.route('/login')
def login_page():
    """显示登录页面"""
    return render_template('login.html')

# 系统主页面路由（需要登录）
@app.route('/system')
# @login_required
def system_page():
    """显示系统主页面"""
    return render_template('鲲鹏9.5.html')

# 更新现有的根路径路由
@app.route('/')
def root():
    """根路径重定向到登录页"""
    return redirect('/login')

# ==================== 工具函数 ====================
def generate_trend_data(production_line, target_date):
    labels = [f"{h:02d}:00" for h in range(24)]
    values = [0] * 24
    target_date_str = target_date.strftime("%Y-%m-%d")
    
    with fault_history_lock:
        for fault in fault_history[production_line]:
            fault_date = fault['start_time'].split(' ')[0]
            if fault_date != target_date_str:
                continue
            try:
                fault_hour = int(fault['start_time'].split(' ')[1].split(':')[0])
                values[fault_hour] += 1
            except:
                continue
    return {'labels': labels, 'values': values}

def realtime_monitor_worker(production_line):
    logger.info(f"启动实时监测工作线程 - 生产线: {production_line}")
    table_name = TABLE_NAMES[0] if production_line == 'M201' else TABLE_NAMES[1]
    processor = realtime_processors[production_line]
    
    while True:
        try:
            with realtime_lock:
                if not realtime_state[production_line]['running']:
                    break
            
            current_dt, predictions = processor.predict_faults(table_name, production_line)
            if not current_dt or not predictions:
                time.sleep(3)
                continue
            
            with realtime_lock:
                state = realtime_state[production_line]
                current_fault_ids = [p['model_key'] for p in predictions if p['value'] == 1]
                new_active = []
                new_history = []
                
                for p in predictions:
                    fault_key = p['model_key']
                    if p['value'] == 1 and fault_key not in [f['model_key'] for f in state['active_faults']]:
                        new_fault = {
                            'id': len(state['active_faults']) + len(state['recent_history']) + 1,
                            'model_key': fault_key,
                            'production_line': production_line,
                            'start_time': current_dt.strftime("%Y-%m-%d %H:%M:%S"),
                            'end_time': None,
                            'duration': 0,
                            'is_active': True,
                            'raw_features': {
                                '物料推送数': processor.last_series.get('物料推送数', 0) if processor.last_series else 0,
                                '物料待抓取数': processor.last_series.get('物料待抓取数', 0) if processor.last_series else 0,
                                '放置容器数': processor.last_series.get('放置容器数', 0) if processor.last_series else 0,
                                '容器上传检测数': processor.last_series.get('容器上传检测数', 0) if processor.last_series else 0
                            }
                        }
                        state['active_faults'].append(new_fault)
                        new_active.append(new_fault)
                        hour = current_dt.hour
                        state['today_trend'][hour] += 1
                    elif p['value'] == 0:
                        for fault in state['active_faults']:
                            if fault['model_key'] == fault_key and fault['is_active']:
                                fault['is_active'] = False
                                fault['end_time'] = current_dt.strftime("%Y-%m-%d %H:%M:%S")
                                fault['duration'] = round((current_dt - datetime.strptime(fault['start_time'], "%Y-%m-%d %H:%M:%S")).total_seconds(), 1)
                                state['recent_history'].insert(0, fault)
                                new_history.append(fault)
                
                state['active_faults'] = [f for f in state['active_faults'] if f['is_active']]
                state['recent_history'] = state['recent_history'][:10]
                state['latest_data'] = {
                    'datetime': current_dt.strftime("%Y-%m-%d %H:%M:%S"),
                    'predictions': predictions,
                    'raw_features': {
                        '物料推送数': processor.last_series.get('物料推送数', 0) if processor.last_series else 0,
                        '物料待抓取数': processor.last_series.get('物料待抓取数', 0) if processor.last_series else 0,
                        '放置容器数': processor.last_series.get('放置容器数', 0) if processor.last_series else 0,
                        '容器上传检测数': processor.last_series.get('容器上传检测数', 0) if processor.last_series else 0
                    }
                }
            
            time.sleep(3)

            if new_active:
                logger.warning(f"检测到新故障 - 生产线: {production_line}, 故障数: {len(new_active)}")
                    
        except Exception as e:
            logger.error(f"实时监测异常: {str(e)}", exc_info=True)
            time.sleep(5)  # 异常时延长等待时间

# ==================== 路由定义 ====================
# 系统概览
@app.route('/api/overview/stats')
def stats():
    return jsonify({
                        'accuracy_rate': 98.5,
                        'accuracy_trend': '+2.3%',
                        'production_lines': 8,
                        'active_lines': 7,
                        'operators_count': 42,
                        'on_duty': 36,
                        'daily_qualified': 12583,
                        'qualified_rate': 98.2
                    })

# 历史故障查询
@app.route('/api/latest-data')
def get_latest_data():
    production_line = request.args.get('line', 'M201')
    date_str = request.args.get('date')
    
    logger.info(f"历史故障查询请求 - 生产线: {production_line}, 日期: {date_str}")

    if production_line not in ['M201', 'M202']:
        logger.warning(f"无效的生产线参数: {production_line}")
        return jsonify({
            'success': False,
            'message': "生产线仅支持M201/M202",
            'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        })
    try:
        if not date_str:
            return jsonify({
                'success': False,
                'message': "请提供日期参数（date=YYYY-MM-DD）",
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            })
        try:
            target_date = datetime.strptime(date_str, "%Y-%m-%d")
        except ValueError:
            return jsonify({
                'success': False,
                'message': "日期格式错误（正确：2025-01-01）",
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            })
        
        table_name = TABLE_NAMES[0] if production_line == 'M201' else TABLE_NAMES[1]
        history_processor = history_processors[production_line]
        if hasattr(history_processor, 'reset_history_state'):
            history_processor.reset_history_state()
        else:
            history_processor.history_state = {}
            history_processor.last_series = None
            history_processor.last_process_time = None
        
        pred_result = history_processor.predict_faults_by_date(table_name, production_line, target_date)
        
        if not pred_result['success']:
            return jsonify({
                'success': False,
                'message': pred_result['message'],
                'code': pred_result['code'],
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                'target_date': date_str,
                'production_line': production_line
            })
        
        batch_data = pred_result['data']
        new_faults_count = 0
        with fault_history_lock:
            line_faults = fault_history[production_line]
            for row in batch_data:
                current_dt_str = row['datetime'].strftime("%Y-%m-%d %H:%M:%S")
                for pred in row['predictions']:
                    model_key = pred['model_key']
                    pred_value = pred['value']
                    
                    if pred_value == 1 and not any(
                        f['model_key'] == model_key and f['is_active'] and f['production_line'] == production_line
                        for f in line_faults
                    ):
                        new_fault = {
                            'id': len(line_faults) + 1,
                            'model_key': model_key,
                            'production_line': production_line,
                            'start_time': current_dt_str,
                            'end_time': None,
                            'duration': 0,
                            'is_active': True
                        }
                        line_faults.append(new_fault)
                        new_faults_count += 1
                    
                    elif pred_value == 0:
                        for fault in line_faults:
                            if fault['model_key'] == model_key and fault['is_active'] and fault['production_line'] == production_line:
                                fault_start = datetime.strptime(fault['start_time'], "%Y-%m-%d %H:%M:%S")
                                fault['duration'] = round(float((row['datetime'] - fault_start).total_seconds()), 1)
                                fault['end_time'] = current_dt_str
                                fault['is_active'] = False
        
        trend_data = generate_trend_data(production_line, target_date)
        with fault_history_lock:
            daily_faults = [
                f for f in fault_history[production_line] 
                if f['start_time'].split(' ')[0] == date_str
            ]
        
        return jsonify({
            'success': True,
            'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'production_line': production_line,
            'target_date': date_str,
            'batch_info': {
                'processed_rows': int(len(batch_data)),
                'new_faults': int(new_faults_count),
                'model_count': int(pred_result['stats']['model_count'])
            },
            'active_faults': [f for f in fault_history[production_line] if f['is_active']],
            'fault_history': daily_faults,
            'trend_data': trend_data,
            'latest_data': batch_data[-1] if batch_data else None
        })
    
        logger.info(f"成功处理历史故障查询，处理行数: {len(batch_data)}")
        
    except Exception as e:
        logger.error(f"历史故障查询异常: {str(e)}", exc_info=True)
        return jsonify({
            'success': False,
            'message': f"数据处理异常: {str(e)}",
            'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        })
        
# 实时监测
@app.route('/api/realtime-monitor')
def realtime_monitor():
    production_line = request.args.get('line', 'M201')
    action = request.args.get('action', 'status')
    
    if production_line not in ['M201', 'M202']:
        return jsonify({
            'success': False,
            'message': "生产线仅支持M201/M202",
            'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        })
    
    with realtime_lock:
        state = realtime_state[production_line]
        
        if action == 'start':
            if state['running']:
                return jsonify({
                    'success': True,
                    'is_running': True,
                    'message': f"{production_line} 实时监测已在运行",
                    'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                })
            realtime_processors[production_line].reset_history_state()
            state['running'] = True
            threading.Thread(
                target=realtime_monitor_worker,
                args=(production_line,),
                daemon=True
            ).start()
            return jsonify({
                'success': True,
                'is_running': True,
                'message': f"{production_line} 实时监测已启动",
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            })
        
        elif action == 'stop':
            if not state['running']:
                return jsonify({
                    'success': True,
                    'is_running': False,
                    'message': f"{production_line} 实时监测已停止",
                    'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                })
            state['running'] = False
            return jsonify({
                'success': True,
                'is_running': False,
                'message': f"{production_line} 实时监测已停止",
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            })
        
        elif action == 'status':
            trend_labels = [f"{h:02d}:00" for h in range(24)]
            return jsonify({
                'success': True,
                'is_running': state['running'],
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                'active_faults': state['active_faults'],
                'recent_history': state['recent_history'],
                'today_trend': {
                    'labels': trend_labels,
                    'values': state['today_trend']
                },
                'latest_data': state['latest_data']
            })
        
        else:
            return jsonify({
                'success': False,
                'message': "无效操作（支持：start/stop/status）",
                'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            })

# 清空缓存
@app.route('/api/clear-cache')
def clear_cache():
    production_line = request.args.get('line')
    with fault_history_lock:
        if production_line and production_line in fault_history:
            fault_history[production_line] = []
            if production_line in history_processors:
                history_processor = history_processors[production_line]
                if hasattr(history_processor, 'reset_history_state'):
                    history_processor.reset_history_state()
                else:
                    history_processor.history_state = {}
                    history_processor.last_series = None
                    history_processor.last_process_time = None
            return jsonify({'success': True, 'message': f'已清空{production_line}的故障历史'})
        elif not production_line:
            for line in fault_history:
                fault_history[line] = []
                if line in history_processors:
                    history_processor = history_processors[line]
                    if hasattr(history_processor, 'reset_history_state'):
                        history_processor.reset_history_state()
                    else:
                        history_processor.history_state = {}
                        history_processor.last_series = None
                        history_processor.last_process_time = None
            return jsonify({'success': True, 'message': '已清空所有故障历史'})
        else:
            return jsonify({'success': False, 'message': '无效的生产线'})

# 获取历史故障
@app.route('/api/history')
def get_history():
    days = int(request.args.get('days', 7))
    production_line = request.args.get('line')
    date_str = request.args.get('date')
    start_date = datetime.now() - timedelta(days=days)
    
    filtered = []
    target_lines = [production_line] if production_line in ['M201', 'M202'] else ['M201', 'M202']
    
    with fault_history_lock:
        for line in target_lines:
            for fault in fault_history[line]:
                fault_time = datetime.strptime(fault['start_time'], "%Y-%m-%d %H:%M:%S")
                if date_str and fault['start_time'].split(' ')[0] != date_str:
                    continue
                if not date_str and fault_time < start_date:
                    continue
                filtered.append(fault)
    
    return jsonify({
        'success': True,
        'count': int(len(filtered)),
        'history': filtered
    })

# 获取生产线列表
@app.route("/api/production-lines", methods=["GET"])
def production_lines():
    production_lines = ["M301", "M302", "M303", "M304", "M305", "M306", "M307", "M308", "M309", "M310"]
    return jsonify({"productionLines": production_lines})

# 获取生产线图表
@app.route("/api/line-charts", methods=["GET"])
def line_charts():
    line = request.args.get("line")
    if not line:
        return jsonify({"charts": []})
    line_charts = [
        f"{line}_产量随时间变化.png",
        f"{line}_合格率随时间变化.png"
    ]
    existing_charts = [chart for chart in line_charts if os.path.exists(os.path.join(CHART_DIR, chart))]
    return jsonify({"charts": existing_charts})

# 获取汇总图表
@app.route("/api/summary-charts", methods=["GET"])
def summary_charts():
    summary_charts = [
        "各生产线平均指标对比图.png",
        "各生产线产量统计对比图.png",
        "各生产线合格率统计对比图.png"
    ]
    existing_summary = [chart for chart in summary_charts if os.path.exists(os.path.join(CHART_DIR, chart))]
    return jsonify({"charts": existing_summary})

# 获取图表文件
@app.route("/charts/<path:filename>", methods=["GET"])
def get_chart(filename):
    filename = unquote(filename)
    if '..' in filename or filename.startswith('/'):
        return "Invalid filename", 400
    filepath = os.path.join(CHART_DIR, filename)
    if not os.path.exists(filepath):
        all_files = os.listdir(CHART_DIR)
        for f in all_files:
            pattern = re.compile(re.escape(filename).replace(r'\ ', r'[ _]'))
            if pattern.search(f):
                filepath = os.path.join(CHART_DIR, f)
                break
        else:
            return "File not found", 404
    return send_from_directory(CHART_DIR, os.path.basename(filepath))

@app.route('/api/schedule/result1')
def get_result1():
    """获取result4-1数据"""
    try:
        # 读取Excel文件
        df = pd.read_excel(RESULT1_PATH)
        
        # 转换为字典格式便于前端显示
        data = {
            'columns': df.columns.tolist(),
            'data': df.values.tolist(),
            'last_updated': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        return jsonify(data)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/schedule/result2')
def get_result2():
    """获取result4-2数据"""
    try:
        # 读取Excel文件
        df = pd.read_excel(RESULT2_PATH)
        
        # 转换为字典格式便于前端显示
        data = {
            'columns': df.columns.tolist(),
            'data': df.values.tolist(),
            'last_updated': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        return jsonify(data)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/schedule/update', methods=['POST'])
def update_schedule_api():
    """更新排班计划（异步处理）"""
    logger.info("接收到排班更新请求")
    global schedule_status
    
    if schedule_status['is_processing']:
        return jsonify({'error': '系统正在处理上一个请求，请稍后再试'}), 429
    
    try:
        # 获取前端传来的工龄分布数据
        data = request.get_json()
        age_distribution = data.get('age_distribution', {})        
        logger.info(f"排班工龄分布: {age_distribution}")  

        # 验证数据格式
        if not data or 'age_distribution' not in data:
            return jsonify({'error': '缺少工龄分布数据'}), 400
        
        age_distribution = data['age_distribution']
        
        # 设置为处理中状态
        schedule_status['is_processing'] = True
        schedule_status['last_error'] = None
        
        # 在后台线程中处理排班计算
        def process_schedule():
            try:
                success = update_schedule(age_distribution)
                schedule_status['last_result'] = success
                if not success:
                    schedule_status['last_error'] = '排班计算失败'
            except Exception as e:
                schedule_status['last_error'] = str(e)
            finally:
                schedule_status['is_processing'] = False
        
        # 启动后台线程
        thread = threading.Thread(target=process_schedule)
        thread.daemon = True
        thread.start()
        
        return jsonify({
            'message': '排班计算已开始，请稍后刷新页面查看结果',
            'processing': True
        })
            
    except Exception as e:
        schedule_status['is_processing'] = False
        logger.error(f"排班更新异常: {str(e)}", exc_info=True)
        return jsonify({'error': str(e)}), 500

@app.route('/api/schedule/status')
def get_schedule_status():
    """获取排班处理状态"""
    return jsonify({
        'is_processing': schedule_status['is_processing'],
        'last_error': schedule_status['last_error'],
        'last_result': schedule_status['last_result']
    })

@app.route('/download/result1')
def download_result1():
    """下载result4-1文件"""
    return send_file(RESULT1_PATH, as_attachment=True)

@app.route('/download/result2')
def download_result2():
    """下载result4-2文件"""
    return send_file(RESULT2_PATH, as_attachment=True)

# Socket.io 模拟
@app.route("/socket.io/")
def socket_io():
    return jsonify({"message": "WebSocket not implemented"}), 200

# 日志查看接口
@app.route('/api/logs')
def get_logs():
    """获取日志文件列表和内容"""
    try:
        log_dir = "logs"
        logs = []
        
        if os.path.exists(log_dir):
            for file in sorted(os.listdir(log_dir)):
                if file.endswith('.log'):
                    file_path = os.path.join(log_dir, file)
                    file_size = os.path.getsize(file_path)
                    logs.append({
                        'name': file,
                        'size': file_size,
                        'modified': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S')
                    })
        
        return jsonify({'success': True, 'logs': logs})
    
    except Exception as e:
        logger.error(f"获取日志列表异常: {str(e)}")
        return jsonify({'success': False, 'error': str(e)})

@app.route('/api/logs/<filename>')
def get_log_content(filename):
    """获取特定日志文件内容"""
    try:
        # 安全校验文件名
        if '..' in filename or not filename.endswith('.log'):
            return jsonify({'success': False, 'error': '无效的文件名'})
        
        file_path = os.path.join('logs', filename)
        if not os.path.exists(file_path):
            return jsonify({'success': False, 'error': '文件不存在'})
        
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        return jsonify({'success': True, 'content': content})
    
    except Exception as e:
        logger.error(f"读取日志文件异常: {str(e)}")
        return jsonify({'success': False, 'error': str(e)})
    

# ==================== 启动应用 ====================
if __name__ == '__main__':
    if not os.path.exists(DATA_FOLDER):
        os.makedirs(DATA_FOLDER)
    
    # 增加超时时间和线程配置
    app.run(
        debug=True, 
        host='0.0.0.0', 
        port=5000,
        threaded=True,  # 启用多线程
        use_reloader=False  # 禁用自动重载，避免干扰
    )
   